package com.jtemimal.controller;

import cn.hutool.core.util.StrUtil;
import com.jtemimal.CommandReq;
import com.jtemimal.resp.CommandResult;
import com.jtemimal.utils.CommandCompletion;
import com.jtemimal.utils.FileColorUtil;
import com.jtemimal.utils.InteractiveCommandExecutor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Controller
public class WebSocketController {

    private static final String OS = System.getProperty("os.name").toLowerCase();
    private static final List<String> INTERACTIVE_COMMANDS = Arrays.asList(
        "vim", "vi", "nano", "less", "more", "top", "htop"
    );

    private final InteractiveCommandExecutor commandExecutor;
    private final SimpMessagingTemplate messagingTemplate;

    public WebSocketController(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
        this.commandExecutor = new InteractiveCommandExecutor(messagingTemplate);
    }

    @MessageMapping("/sendMessage")
    @SendTo("/topic/messages")
    public CommandResult processMessageFromClient(CommandReq request) {
        String type = request.getType();
        String command = request.getCommand();
        
        // 处理交互式命令
        if ("interactive".equals(type)) {
            return commandExecutor.startCommand(request.getSessionId(), command);
        } else if ("interactive_input".equals(type)) {
            commandExecutor.sendInput(request.getSessionId(), command);
            return null;
        } else if ("terminate".equals(type)) {
            commandExecutor.terminateCommand(request.getSessionId());
            return null;
        }
        
        // 处理补全请求
        if ("completion".equals(type)) {
            List<String> suggestions = CommandCompletion.getCompletions(command);
            return new CommandResult(suggestions);
        }
        
        // 处理普通命令
        if ("command".equals(type)) {
            log.info("Received command: {}", command);
            command = StrUtil.removeAllLineBreaks(command);
            
            if (Objects.isNull(command)) {
                return new CommandResult(null, "command is null");
            }

            // 处理 ls 命令
            if (command.trim().startsWith("ls")) {
                return executeLsCommand(command);
            }

            // 处理其他命令
            return executeCommand(command);
        }

        return new CommandResult(null, "Unknown command type: " + type);
    }

    private CommandResult executeLsCommand(String command) {
        try {
            CommandLine cmdLine;
            if (OS.contains("win")) {
                // Windows 系统使用 dir 命令
                command = command.replace("ls", "dir");
                cmdLine = CommandLine.parse("cmd.exe");
                cmdLine.addArgument("/c");
                cmdLine.addArgument(command, false);
            } else {
                // Unix-like 系统
                cmdLine = CommandLine.parse(command);
                // 添加颜色支持
                cmdLine.addArgument("--color=always", false);
            }

            DefaultExecutor executor = new DefaultExecutor();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
            PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, errorStream);
            executor.setStreamHandler(streamHandler);

            ExecuteWatchdog watchdog = new ExecuteWatchdog(10000);
            executor.setWatchdog(watchdog);

            try {
                executor.execute(cmdLine);
                String output = outputStream.toString();
                String error = errorStream.toString();
                
                // 如果是 Windows，转换输出格式为类 Unix 格式
                if (OS.contains("win")) {
                    output = convertWindowsOutput(output);
                }
                
                return new CommandResult(output, error);
            } catch (Exception e) {
                if (watchdog.killedProcess()) {
                    log.error("ls command was terminated due to timeout.");
                } else {
                    log.error("ls execution failed: {}", e.getMessage());
                }
                return new CommandResult(null, e.getMessage());
            }
        } catch (Exception e) {
            return new CommandResult(null, "ls: " + e.getMessage());
        }
    }

    private CommandResult executeCommand(String command) {
        try {
            CommandLine cmdLine = CommandLine.parse(command);
            DefaultExecutor executor = new DefaultExecutor();

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
            PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, errorStream);
            executor.setStreamHandler(streamHandler);

            ExecuteWatchdog watchdog = new ExecuteWatchdog(10000);
            executor.setWatchdog(watchdog);

            executor.execute(cmdLine);
            return new CommandResult(outputStream.toString(), errorStream.toString());
        } catch (Exception e) {
            return new CommandResult(null, e.getMessage());
        }
    }

    private String convertWindowsOutput(String windowsOutput) {
        // 转换 Windows dir 命令输出为类 Unix ls 格式
        StringBuilder unixStyle = new StringBuilder();
        String[] lines = windowsOutput.split("\r?\n");
        String currentPath = "";
        
        for (String line : lines) {
            line = line.trim();
            if (line.isEmpty()) {
                continue;
            }
            
            // 获取当前目录路径
            if (line.startsWith("Directory of")) {
                currentPath = line.substring("Directory of".length()).trim();
                continue;
            }
            
            // 解析 Windows 格式的文件信息
            if (line.matches(".*\\d{2}/\\d{2}/\\d{4}.*")) {
                String[] parts = line.trim().split("\\s+");
                if (parts.length >= 4) {
                    // 获取文件名（可能包含空格）
                    String name = String.join(" ", Arrays.copyOfRange(parts, 3, parts.length));
                    
                    // 如果包含 <DIR>，需要移除它
                    name = name.replace("<DIR>", "").trim();
                    
                    // 创建完整的文件路径
                    String fullPath = currentPath + File.separator + name;
                    File file = new File(fullPath);
                    
                    // 使用 FileColorUtil 添加颜色
                    unixStyle.append(FileColorUtil.colorize(file)).append("  ");
                }
            }
        }
        
        return unixStyle.toString() + "\n";
    }

    @MessageMapping("/terminateCommand")
    public void terminateCommand(String sessionId) {
        commandExecutor.terminateCommand(sessionId);
    }
}